home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pine / pine3.07 / c-client / mbox.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-29  |  6.9 KB  |  231 lines

  1. /*
  2.  * Program:    MBOX mail routines
  3.  *
  4.  * Author:    Mark Crispin
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: MRC@CAC.Washington.EDU
  11.  *
  12.  * Date:    10 March 1992
  13.  * Last Edited:    26 April 1992
  14.  *
  15.  * Copyright 1992 by the University of Washington
  16.  *
  17.  *  Permission to use, copy, modify, and distribute this software and its
  18.  * documentation for any purpose and without fee is hereby granted, provided
  19.  * that the above copyright notice appears in all copies and that both the
  20.  * above copyright notice and this permission notice appear in supporting
  21.  * documentation, and that the name of the University of Washington not be
  22.  * used in advertising or publicity pertaining to distribution of the software
  23.  * without specific, written prior permission.  This software is made
  24.  * available "as is", and
  25.  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
  26.  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
  27.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
  28.  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
  29.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  30.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
  31.  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
  32.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33.  *
  34.  */
  35.  
  36. #include <stdio.h>
  37. #include <ctype.h>
  38. #include <pwd.h>
  39. #include <netdb.h>
  40. #include <errno.h>
  41. extern int errno;        /* just in case */
  42. #include <sys/types.h>
  43. #include <sys/file.h>
  44. #include <sys/stat.h>
  45. #include <sys/time.h>
  46. #include <sys/uio.h>
  47. #include "osdep.h"
  48. #include "mail.h"
  49. #include "mbox.h"
  50. #include "bezerk.h"
  51. #include "misc.h"
  52.  
  53. /* MBOX mail routines */
  54.  
  55.  
  56. /* Driver dispatch used by MAIL */
  57.  
  58. DRIVER mboxdriver = {
  59.   (DRIVER *) NIL,        /* next driver */
  60.   mbox_valid,            /* mailbox is valid for us */
  61.   mbox_find,            /* find mailboxes */
  62.   bezerk_find_bboards,        /* find bboards */
  63.   mbox_open,            /* open mailbox */
  64.   bezerk_close,            /* close mailbox */
  65.   bezerk_fetchfast,        /* fetch message "fast" attributes */
  66.   bezerk_fetchflags,        /* fetch message flags */
  67.   bezerk_fetchenvelope,        /* fetch message envelopes */
  68.   bezerk_fetchheader,        /* fetch message header only */
  69.   bezerk_fetchtext,        /* fetch message body only */
  70.   bezerk_fetchbody,        /* fetch message body section */
  71.   bezerk_setflag,        /* set message flag */
  72.   bezerk_clearflag,        /* clear message flag */
  73.   bezerk_search,        /* search for message based on criteria */
  74.   mbox_ping,            /* ping mailbox to see if still alive */
  75.   mbox_check,            /* check for new messages */
  76.   mbox_expunge,            /* expunge deleted messages */
  77.   bezerk_copy,            /* copy messages to another mailbox */
  78.   bezerk_move,            /* move messages to another mailbox */
  79.   bezerk_gc            /* garbage collect stream */
  80. };
  81.  
  82. /* Test for valid header */
  83.  
  84. #define VALID (s[1] == 'r') && (s[2] == 'o') && (s[3] == 'm') && \
  85.   (s[4] == ' ') && (t = strchr (s+5,'\n')) && (t-s >= 27) && (t[-5] == ' ') &&\
  86.   (t[(rn = -4 * (t[-9] == ' '))-8] == ':') && \
  87.   ((sysv = 3 * (t[rn-11] == ' ')) || t[rn-11] == ':') && \
  88.   (t[rn+sysv-14] == ' ') && (t[rn+sysv-17] == ' ') && \
  89.   (t[rn+sysv-21] == ' ')
  90.  
  91.  
  92. /* MBOX mail validate mailbox
  93.  * Accepts: mailbox name
  94.  * Returns: our driver if name is valid, otherwise calls valid in next driver
  95.  */
  96.  
  97. DRIVER *mbox_valid (name)
  98.     char *name;
  99. {
  100.   int fd;
  101.   char s[MAILTMPLEN];
  102.   char *t;
  103.   int rn,sysv;
  104.   int ret = NIL;
  105.   struct stat sbuf;
  106.                 /* only consider INBOX */
  107.   if (!strcmp (ucase (strcpy (s,name)),"INBOX")) {
  108.                 /* make what the file name would be */
  109.     sprintf (s,"%s/mbox",getpwuid (geteuid ())->pw_dir);
  110.                 /* file exist? */
  111.     if ((stat(s,&sbuf) == 0) && (fd = open (s,O_RDONLY,NIL)) >= 0) {
  112.                 /* allow empty or valid file */
  113.       if ((sbuf.st_size == 0) || ((read (fd,s,MAILTMPLEN-1) >= 0) &&
  114.                   (*s == 'F') && VALID)) ret = T;
  115.       close (fd);        /* close the file */
  116.     }
  117.   }
  118.   return ret ? &mboxdriver :
  119.     (mboxdriver.next ? (*mboxdriver.next->valid) (name) : NIL);
  120. }
  121.  
  122.  
  123. /* MBOX mail find list of mailboxes
  124.  * Accepts: mail stream
  125.  *        pattern to search
  126.  */
  127.  
  128. void mbox_find (stream,pat)
  129.     MAILSTREAM *stream;
  130.     char *pat;
  131. {
  132.   /* Always a no-op since bezerk will do this */
  133. }
  134.  
  135. /* MBOX mail open
  136.  * Accepts: stream to open
  137.  * Returns: stream on success, NIL on failure
  138.  */
  139.  
  140. MAILSTREAM *mbox_open (stream)
  141.     MAILSTREAM *stream;
  142. {
  143.   MAILSTREAM *ret;
  144.   unsigned long i = 1;
  145.   unsigned long recent = 0;
  146.   char tmp[MAILTMPLEN];
  147.                 /* change mailbox file name */
  148.   sprintf (tmp,"%s/mbox",getpwuid (geteuid ())->pw_dir);
  149.   fs_give ((void **) &stream->mailbox);
  150.   stream->mailbox = cpystr (tmp);
  151.   stream->silent = T;        /* now do the open */
  152.   if (ret = bezerk_open (stream)) {
  153.     mbox_ping (ret);        /* snarf new mail */
  154.                 /* notify upper level of mailbox sizes */
  155.     mail_exists (stream,stream->nmsgs);
  156.     while (i <= stream->nmsgs) if (mail_elt (stream,i++)->recent) ++recent;
  157.     mail_recent (stream,recent);/* including recent messages */
  158.   }
  159.   stream->silent = NIL;        /* allow external events now */
  160.   return ret;
  161. }
  162.  
  163. /* MBOX mail ping mailbox
  164.  * Accepts: MAIL stream
  165.  * Returns: T if stream alive, else NIL
  166.  * No-op for readonly files, since read/writer can expunge it from under us!
  167.  */
  168.  
  169. long mbox_ping (stream)
  170.     MAILSTREAM *stream;
  171. {
  172.   int fd,sfd;
  173.   char *s;
  174.   long size;
  175.   struct stat sbuf;
  176.   char lock[MAILTMPLEN],slock[MAILTMPLEN];
  177.   if (LOCAL && !stream->readonly && !stream->lock) {
  178.     mm_critical (stream);    /* go critical */
  179.                 /* calculate name of bezerk file */
  180.     sprintf (LOCAL->buf,MAILFILE,getpwuid (geteuid ())->pw_name);
  181.     if ((sfd = bezerk_lock (LOCAL->buf,O_RDWR,NIL,slock,LOCK_EX)) >= 0) {
  182.       fstat (sfd,&sbuf);    /* get size of the poop */
  183.       if (size = sbuf.st_size){ /* non-empty? */
  184.                 /* yes, read it */
  185.     read (sfd,s = (char *) fs_get (sbuf.st_size + 1),size);
  186.     s[sbuf.st_size] = '\0';    /* tie it off */
  187.     if ((fd = bezerk_lock (LOCAL->fname,O_WRONLY|O_APPEND,NIL,lock,
  188.                    LOCK_EX)) >= 0) {
  189.       fstat (fd,&sbuf);    /* get current file size before write*/
  190.       if (write (fd,s,size) >= 0) ftruncate (sfd,0);
  191.       else {        /* failed */
  192.         sprintf (LOCAL->buf,"New mail copy failed: %s",strerror (errno));
  193.         mm_log (LOCAL->buf,ERROR);
  194.         ftruncate (fd,sbuf.st_size);
  195.       }
  196.       fsync (fd);        /* force out the update */
  197.       bezerk_unlock (fd,NIL,lock);
  198.     }
  199.     fs_give ((void **) &s);    /* flush the poop now */
  200.       }
  201.                 /* all done with update */
  202.       bezerk_unlock (sfd,NIL,slock);
  203.     }
  204.     mm_nocritical (stream);    /* release critical */
  205.   }
  206.   return bezerk_ping (stream);    /* do the bezerk routine now */
  207. }
  208.  
  209. /* MBOX mail check mailbox
  210.  * Accepts: MAIL stream
  211.  */
  212.  
  213. void mbox_check (stream)
  214.     MAILSTREAM *stream;
  215. {
  216.                 /* do local ping, then do bezerk routine */
  217.   if (mbox_ping (stream)) bezerk_check (stream);
  218. }
  219.  
  220.  
  221. /* MBOX mail expunge mailbox
  222.  * Accepts: MAIL stream
  223.  */
  224.  
  225. void mbox_expunge (stream)
  226.     MAILSTREAM *stream;
  227. {
  228.   bezerk_expunge (stream);    /* do expunge */
  229.   mbox_ping (stream);        /* do local ping */
  230. }
  231.